package com.ms.service.db.jedis;

import java.util.ArrayList;
import java.util.List;
//import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.exceptions.JedisException;

public class JedisDatabase {

	/**
	 * log
	 */
	private Log log = LogFactory.getLog(JedisManager.class);
	
	/**
	 * IP列表
	 */
	private List<String> Host;
	
	private JedisPoolConfig jedisPoolConfig;
	
	//private List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
     
	//private JedisPool jedisPool;
	
	private List<String> shards = new ArrayList<String>();
	
	private JedisPool  jedisPool;
	
	private boolean isInit = false;
	private boolean isInitConfig = false;
	
	/**
	 * 初始化
	 */
	public void initial()
	{	
		if(isInit){
			return;
		}
		
        if(Host.size() != 0){
            for (int i = 0; i < Host.size(); i++) {      
				/*JedisShardInfo info = new JedisShardInfo(Host.get(i));
                shards = Arrays.asList(info);
                */
                shards.add(Host.get(i));
                if(log.isInfoEnabled()){
                	log.info(shards);
                }
            }
        }else{
        	if(log.isErrorEnabled()){
        		log.error("請檢查Jedis配置，host為必填！格式[IP:PORT]");
        	}
        }
        
        String hostinfo = shards.get(0);
        
        int last =hostinfo.lastIndexOf("/");
        String dbindex = hostinfo.substring(last+1);
        String host = hostinfo.substring(0, last);
        last = host.lastIndexOf("/");
        host=host.substring(last+1);
        String[] realhost = host.split(":");
        
        jedisPoolConfig.setMaxWaitMillis(-1);
        jedisPoolConfig.setMinEvictableIdleTimeMillis(1800000);
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(-1);
        

        jedisPool = new JedisPool(jedisPoolConfig,realhost[0],Integer.valueOf(realhost[1]),3000,null,Integer.valueOf(dbindex)); //new JedisPool(jedisPoolConfig, shards);
        if(jedisPool != null){
        	if(log.isInfoEnabled()){
        		log.info("Jedis start finish !!!!");
        	}
        }
        isInit = true;
    }
	
	/**
	 * 初始化設定
	 */
	public void initialJedisConfiguration(JedisPoolConfig jedisConfig , String hostName){
		
		if(isInitConfig){
			return;
		}
		
		try{
			Class.forName("redis.clients.jedis.JedisPoolConfig");
		}catch(ClassNotFoundException e){
			if(log.isErrorEnabled()){
				log.error("Jedis library not found !!!!" , e);
			}
		}
		
		jedisPoolConfig = jedisConfig;
		Host = new ArrayList<String>();
	    Host.add(hostName);
		
	     if(log.isInfoEnabled()){
	    	 log.info("Jedis Configuration initial finish !!!!");
	     }

	}
	
	public synchronized Jedis getResource(){
		
		Jedis jedis = null;
		
		if(jedisPool == null){
			initial();
		}
		boolean broken = false;
		
		try {
	        jedis = jedisPool.getResource();
	        return jedis; //模板方法
	    } catch (JedisException e) {
	        broken = handleJedisException(e);
	        throw e;
	    } finally {
	    	closeResource(jedis, broken);
	    }
    }
    
	@SuppressWarnings("deprecation")
	public synchronized void returnResource(Jedis jedis){
		
		try {
			jedisPool.returnResourceObject(jedis);
			//jedisPool.returnResourceObject(jedis);
		} catch (Exception jedisException) {
			if (jedisException instanceof JedisConnectionException) {
				//jedisPool.returnBrokenResource(jedis);
				jedisPool.returnResourceObject(jedis);
	            log.error("Redis connection lost.", jedisException);
	        } else{
	        	log.error("return back jedis failed, will fore close the jedis.", jedisException);
            	jedis.close();
	        }
		}
    }
    
    public synchronized void destroy(){
    	jedisPool.destroy();
    }
    
    
    /**
     * 連線錯誤
     */
    protected boolean handleJedisException(JedisException jedisException) {
    	if (jedisException instanceof JedisConnectionException) {
            log.error("Redis connection lost.", jedisException);
        } else if (jedisException instanceof JedisDataException) {
            // dataException, isBroken=false
            return false;
        } else {
            log.error("Jedis exception happen.", jedisException);
        }
        return true;
    }
    
    protected void closeResource(Jedis jedis, boolean conectionBroken) {
        try {
            if (conectionBroken) {
               //jedisPool.returnBrokenResource(jedis);
            	jedisPool.returnResourceObject(jedis);
            }
        } catch (Exception e) {
            log.error("return back jedis failed, will fore close the jedis.", e);
            jedis.close();
        }
    }
}
